package com.pycredit.config;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.lang3.StringUtils;

import com.pycredit.exception.BizException;
import com.pycredit.type.ExceptionType;

/**
 * @category 配置获取初始化
 * @author yiz
 * @date 2016年5月23日 下午3:49:54
 * @version 1.0.0 
 * @copyright pycredit.cn
 */
public class CostModelConfig {

	/**
	 * @category 字段类型
	 */
	private static Map<String, Double> filedType;

	/**
	 * @category 风险控制成本系数
	 */
	private static Map<String, Double> productForm;

	/**
	 * @category 用户权重
	 */
	private static List<List<String[]>> userWeightList;

	/**
	 * @category 日常公用费用分摊比率
	 */
	private static List<Double> dailyFeeRatio;

	/**
	 * @category 员工薪水
	 */
	private static Map<String, Double> personSalary;

	private static double r;

	private static double dailyDeal;

	private static int workDay;

	private static double c;

	private static CostModelConfig costConfig = null;

	public synchronized static CostModelConfig getInstance() {
		if (costConfig == null) {
			costConfig = new CostModelConfig();
			init();
		}
		return costConfig;
	}

	private CostModelConfig() {

	}

	private static void init() {
		Properties props = new Properties();
		try {
			String fileName = "costmodel.properties";
			InputStream inputStream = null;
			try {
				inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName); // properties.load(Prop.class.getResourceAsStream(fileName));
				if (inputStream == null)
					throw new IllegalArgumentException("Properties file not found in classpath: " + fileName);
				props = new Properties();
				props.load(new InputStreamReader(inputStream, "UTF-8"));
			} catch (IOException e) {
				throw new Exception("Error loading properties file.", e);
			}
			filedType = new HashMap<String, Double>();
			filedType = propSetToMap(props, getFiledList(props, "filed_types"), filedType);

			productForm = new HashMap<String, Double>();
			productForm = propSetToMap(props, getFiledList(props, "project_forms"), productForm);

			userWeightList = new ArrayList<List<String[]>>();
			userWeightList = propSetToListList(props, getFiledList(props, "user_weights"), userWeightList);

			r = Double.valueOf(props.getProperty("user_R"));

			c = Double.valueOf(props.getProperty("code_C"));

			dailyDeal = Double.valueOf(props.getProperty("daily_deal"));

			workDay = Integer.valueOf(props.getProperty("work_day"));

			dailyFeeRatio = new ArrayList<Double>();
			dailyFeeRatio = propSetDoubleToList(props, "daily_fee_ratio", dailyFeeRatio);

			personSalary = new HashMap<String, Double>();
			personSalary = propSetToMap(props, getFiledList(props, "person_salarys"), personSalary);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static Map<String, Double> propSetToMap(Properties props, List<String> keys, Map<String, Double> map)
			throws BizException {
		for (String key : keys) {
			String value = props.getProperty(key);
			if (StringUtils.isBlank(value)) {
				throw new BizException(ExceptionType.CA_0001.getCode(), ExceptionType.CA_0001.getMsg());
			} else {
				try {
					map.put(key, Double.valueOf(value));
				} catch (NumberFormatException e) {
					throw new BizException(ExceptionType.CA_0002.getCode(), ExceptionType.CA_0002.getMsg());
				}
			}
		}
		return map;
	}

	private static List<List<String[]>> propSetToListList(Properties props, List<String> keys,
			List<List<String[]>> list) throws BizException {
		for (String key : keys) {
			String value = props.getProperty(key);
			if (StringUtils.isBlank(value)) {
				throw new BizException(ExceptionType.CA_0001.getCode(), ExceptionType.CA_0001.getMsg());
			} else {
				try {
					String[] vals = value.split(";");
					//array转List
					List<String[]> curList = new ArrayList<String[]>();
					for (String val : vals) {
						//切割,
						String[] ss = val.split(",");
						curList.add(ss);
					}
					list.add(curList);
				} catch (Exception e) {
					throw new BizException(ExceptionType.CA_0002.getCode(), ExceptionType.CA_0002.getMsg());
				}
			}
		}
		return list;
	}

	private static List<Double> propSetDoubleToList(Properties props, String key, List<Double> list)
			throws BizException {
		String value = props.getProperty(key);
		if (StringUtils.isBlank(value)) {
			throw new BizException(ExceptionType.CA_0001.getCode(), ExceptionType.CA_0001.getMsg());
		} else {
			try {
				String[] vals = value.split(",");
				for (String val : vals) {
					list.add(Double.valueOf(val));
				}
			} catch (Exception e) {
				throw new BizException(ExceptionType.CA_0002.getCode(), ExceptionType.CA_0002.getMsg());
			}
		}
		return list;
	}

	private static List<String> getFiledList(Properties props, String filed) throws BizException {
		List<String> filedTypeList = new ArrayList<String>();
		String fileds = props.getProperty(filed);
		if (StringUtils.isBlank(fileds)) {
			throw new BizException(ExceptionType.CA_0001.getCode(), ExceptionType.CA_0001.getMsg());
		} else {
			String[] filedArr = fileds.split(",");
			for (String filedVal : filedArr) {
				filedTypeList.add(filedVal);
			}
		}
		return filedTypeList;
	}

	public static CostModelConfig getCostConfig() {
		return costConfig;
	}

	public Map<String, Double> getFiledType() {
		return filedType;
	}

	public List<List<String[]>> getUserWeightList() {
		return userWeightList;
	}

	public double getR() {
		return r;
	}

	public double getDailyDeal() {
		return dailyDeal;
	}

	public int getWorkDay() {
		return workDay;
	}

	public double getC() {
		return c;
	}

	public List<Double> getDailyFeeRatio() {
		return dailyFeeRatio;
	}

	public Map<String, Double> getProductForm() {
		return productForm;
	}

	public Map<String, Double> getPersonSalary() {
		return personSalary;
	}

}
